// 游戏状态枚举
const GameState = {
	READY: 0, // 准备开始
	PLAYING: 1, // 游戏中
	PAUSED: 2, // 暂停
	OVER: 3 // 游戏结束
};

// 方向枚举
const Direction = {
	UP: 0,
	RIGHT: 1,
	DOWN: 2,
	LEFT: 3
};

// 贪吃蛇游戏类
class SnakeGame {
	constructor(options) {
		// 画布上下文
		this.ctx = options.ctx;
		// 画布宽度
		this.canvasWidth = options.width || 300;
		// 画布高度
		this.canvasHeight = options.height || 300;
		// 格子大小
		this.gridSize = options.gridSize || 15;
		// 游戏速度 (ms)
		this.speed = options.speed || 200;
		// 游戏状态
		this.state = GameState.READY;
		// 分数
		this.score = 0;
		// 最高分
		this.highScore = 0;
		// 游戏循环定时器
		this.timer = null;

		// 计算网格数量
		this.gridWidth = Math.floor(this.canvasWidth / this.gridSize);
		this.gridHeight = Math.floor(this.canvasHeight / this.gridSize);

		// 初始化游戏
		this.init();
	}

	// 初始化游戏
	init() {
		// 初始化蛇
		this.snake = [{
				x: Math.floor(this.gridWidth / 2),
				y: Math.floor(this.gridHeight / 2)
			},
			{
				x: Math.floor(this.gridWidth / 2) - 1,
				y: Math.floor(this.gridHeight / 2)
			}
		];

		// 初始方向（向右）
		this.direction = Direction.RIGHT;
		// 下一个方向（用于防止在一次更新周期内多次改变方向导致自杀）
		this.nextDirection = this.direction;

		// 初始化食物
		this.food = this.generateFood();

		// 重置分数
		this.score = 0;

		// 重置游戏状态
		this.state = GameState.READY;
	}

	// 开始游戏
	start() {
		if (this.state === GameState.READY || this.state === GameState.OVER) {
			this.state = GameState.PLAYING;
			this.startGameLoop();
		} else if (this.state === GameState.PAUSED) {
			this.state = GameState.PLAYING;
			this.startGameLoop();
		}
	}

	// 暂停游戏
	pause() {
		if (this.state === GameState.PLAYING) {
			this.state = GameState.PAUSED;
			clearInterval(this.timer);
		}
	}

	// 重新开始游戏
	restart() {
		clearInterval(this.timer);
		this.init();
		this.start();
	}

	// 游戏循环
	startGameLoop() {
		clearInterval(this.timer);
		this.timer = setInterval(() => {
			this.update();
			this.render();
		}, this.speed);
	}

	// 更新游戏状态
	update() {
		if (this.state !== GameState.PLAYING) return;

		// 更新方向
		this.direction = this.nextDirection;

		// 获取蛇头
		const head = {
			x: this.snake[0].x,
			y: this.snake[0].y
		};

		// 根据方向移动蛇头
		switch (this.direction) {
			case Direction.UP:
				head.y -= 1;
				break;
			case Direction.RIGHT:
				head.x += 1;
				break;
			case Direction.DOWN:
				head.y += 1;
				break;
			case Direction.LEFT:
				head.x -= 1;
				break;
		}

		// 检查是否撞墙
		if (head.x < 0 || head.x >= this.gridWidth || head.y < 0 || head.y >= this.gridHeight) {
			this.gameOver();
			return;
		}

		// 检查是否撞到自己（从第二个身体部分开始检查）
		for (let i = 1; i < this.snake.length; i++) {
			if (head.x === this.snake[i].x && head.y === this.snake[i].y) {
				this.gameOver();
				return;
			}
		}

		// 将新蛇头添加到蛇身体前面
		this.snake.unshift(head);

		// 检查是否吃到食物
		if (head.x === this.food.x && head.y === this.food.y) {
			// 增加分数
			this.score += 10;
			// 更新最高分
			this.highScore = Math.max(this.score, this.highScore);
			// 生成新食物
			this.food = this.generateFood();
		} else {
			// 如果没有吃到食物，移除蛇尾
			this.snake.pop();
		}
	}

	// 渲染游戏
	render() {
		// 清空画布
		this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

		// 绘制背景网格
		this.drawGrid();

		// 绘制蛇
		this.drawSnake();

		// 绘制食物
		this.drawFood();

		// 绘制分数
		this.drawScore();

		// 如果游戏结束，绘制游戏结束信息
		if (this.state === GameState.OVER) {
			this.drawGameOver();
		}

		// 如果游戏暂停，绘制暂停信息
		if (this.state === GameState.PAUSED) {
			this.drawPaused();
		}

		// 使用uni-app的方式刷新画布
		if (typeof this.ctx.draw === 'function') {
			this.ctx.draw();
		}
	}

	// 绘制网格
	drawGrid() {
		this.ctx.strokeStyle = '#EEEEEE';
		this.ctx.lineWidth = 0.5;

		// 绘制垂直线
		for (let x = 0; x <= this.canvasWidth; x += this.gridSize) {
			this.ctx.beginPath();
			this.ctx.moveTo(x, 0);
			this.ctx.lineTo(x, this.canvasHeight);
			this.ctx.stroke();
		}

		// 绘制水平线
		for (let y = 0; y <= this.canvasHeight; y += this.gridSize) {
			this.ctx.beginPath();
			this.ctx.moveTo(0, y);
			this.ctx.lineTo(this.canvasWidth, y);
			this.ctx.stroke();
		}
	}

	// 绘制蛇
	drawSnake() {
		// 绘制蛇身
		for (let i = 1; i < this.snake.length; i++) {
			const segment = this.snake[i];
			this.ctx.fillStyle = '#4CAF50';
			this.ctx.fillRect(
				segment.x * this.gridSize,
				segment.y * this.gridSize,
				this.gridSize,
				this.gridSize
			);

			// 绘制蛇身内部
			this.ctx.fillStyle = '#81C784';
			this.ctx.fillRect(
				segment.x * this.gridSize + 2,
				segment.y * this.gridSize + 2,
				this.gridSize - 4,
				this.gridSize - 4
			);
		}

		// 绘制蛇头
		const head = this.snake[0];
		this.ctx.fillStyle = '#388E3C';
		this.ctx.fillRect(
			head.x * this.gridSize,
			head.y * this.gridSize,
			this.gridSize,
			this.gridSize
		);

		// 绘制蛇头内部
		this.ctx.fillStyle = '#66BB6A';
		this.ctx.fillRect(
			head.x * this.gridSize + 2,
			head.y * this.gridSize + 2,
			this.gridSize - 4,
			this.gridSize - 4
		);

		// 绘制蛇眼睛
		this.ctx.fillStyle = '#000000';

		// 根据方向绘制眼睛
		switch (this.direction) {
			case Direction.UP:
				this.ctx.fillRect(head.x * this.gridSize + 3, head.y * this.gridSize + 3, 2, 2);
				this.ctx.fillRect(head.x * this.gridSize + this.gridSize - 5, head.y * this.gridSize + 3, 2, 2);
				break;
			case Direction.RIGHT:
				this.ctx.fillRect(head.x * this.gridSize + this.gridSize - 5, head.y * this.gridSize + 3, 2, 2);
				this.ctx.fillRect(head.x * this.gridSize + this.gridSize - 5, head.y * this.gridSize + this
					.gridSize - 5, 2, 2);
				break;
			case Direction.DOWN:
				this.ctx.fillRect(head.x * this.gridSize + 3, head.y * this.gridSize + this.gridSize - 5, 2, 2);
				this.ctx.fillRect(head.x * this.gridSize + this.gridSize - 5, head.y * this.gridSize + this
					.gridSize - 5, 2, 2);
				break;
			case Direction.LEFT:
				this.ctx.fillRect(head.x * this.gridSize + 3, head.y * this.gridSize + 3, 2, 2);
				this.ctx.fillRect(head.x * this.gridSize + 3, head.y * this.gridSize + this.gridSize - 5, 2, 2);
				break;
		}
	}

	// 绘制食物
	drawFood() {
		this.ctx.fillStyle = '#F44336';
		this.ctx.beginPath();
		this.ctx.arc(
			this.food.x * this.gridSize + this.gridSize / 2,
			this.food.y * this.gridSize + this.gridSize / 2,
			this.gridSize / 2,
			0,
			Math.PI * 2
		);
		this.ctx.fill();

		// 绘制食物高光
		this.ctx.fillStyle = '#FFFFFF';
		this.ctx.beginPath();
		this.ctx.arc(
			this.food.x * this.gridSize + this.gridSize / 2 - 2,
			this.food.y * this.gridSize + this.gridSize / 2 - 2,
			this.gridSize / 6,
			0,
			Math.PI * 2
		);
		this.ctx.fill();
	}

	// 绘制分数
	drawScore() {
		this.ctx.fillStyle = '#000000';
		this.ctx.font = '16px Arial';
		this.ctx.textAlign = 'left';
		this.ctx.fillText(`分数: ${this.score}`, 10, 25);
		this.ctx.fillText(`最高分: ${this.highScore}`, 10, 50);
	}

	// 绘制游戏结束信息
	drawGameOver() {
		// 半透明背景
		this.ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
		this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);

		// 游戏结束文字
		this.ctx.fillStyle = '#FFFFFF';
		this.ctx.font = 'bold 24px Arial';
		this.ctx.textAlign = 'center';
		this.ctx.fillText('游戏结束', this.canvasWidth / 2, this.canvasHeight / 2 - 30);

		// 分数信息
		this.ctx.font = '18px Arial';
		this.ctx.fillText(`最终分数: ${this.score}`, this.canvasWidth / 2, this.canvasHeight / 2 + 10);

		// 重新开始提示
		this.ctx.font = '16px Arial';
		this.ctx.fillText('点击屏幕重新开始', this.canvasWidth / 2, this.canvasHeight / 2 + 50);
	}

	// 绘制暂停信息
	drawPaused() {
		// 半透明背景
		this.ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
		this.ctx.fillRect(0, 0, this.canvasWidth, this.canvasHeight);

		// 暂停文字
		this.ctx.fillStyle = '#FFFFFF';
		this.ctx.font = 'bold 24px Arial';
		this.ctx.textAlign = 'center';
		this.ctx.fillText('游戏暂停', this.canvasWidth / 2, this.canvasHeight / 2);

		// 继续提示
		this.ctx.font = '16px Arial';
		this.ctx.fillText('点击屏幕继续', this.canvasWidth / 2, this.canvasHeight / 2 + 40);
	}

	// 生成食物
	generateFood() {
		// 创建一个候选位置列表（所有不是蛇身体的位置）
		const availablePositions = [];

		for (let x = 0; x < this.gridWidth; x++) {
			for (let y = 0; y < this.gridHeight; y++) {
				// 检查该位置是否被蛇占用
				let isSnake = false;
				for (let i = 0; i < this.snake.length; i++) {
					if (this.snake[i].x === x && this.snake[i].y === y) {
						isSnake = true;
						break;
					}
				}

				// 如果不是蛇，添加到可用位置
				if (!isSnake) {
					availablePositions.push({
						x,
						y
					});
				}
			}
		}

		// 随机选择一个可用位置
		if (availablePositions.length > 0) {
			const randomIndex = Math.floor(Math.random() * availablePositions.length);
			return availablePositions[randomIndex];
		}

		// 如果没有可用位置（极少情况），返回一个默认位置
		return {
			x: 0,
			y: 0
		};
	}

	// 改变方向
	changeDirection(newDirection) {
		// 防止180度转弯（自杀）
		if (
			(this.direction === Direction.UP && newDirection === Direction.DOWN) ||
			(this.direction === Direction.DOWN && newDirection === Direction.UP) ||
			(this.direction === Direction.LEFT && newDirection === Direction.RIGHT) ||
			(this.direction === Direction.RIGHT && newDirection === Direction.LEFT)
		) {
			return;
		}

		this.nextDirection = newDirection;
	}

	// 游戏结束
	gameOver() {
		this.state = GameState.OVER;
		clearInterval(this.timer);
	}
}

// 导出
export {
	SnakeGame,
	GameState,
	Direction
};